package com.kws.tool.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.kws.common.core.domain.R;
import com.kws.system.api.domain.MerchantDto;
import com.kws.tool.config.AliIdCardReturnAddress;
import com.kws.tool.dto.ResultDto;
import com.kws.tool.dto.UserDto;
import com.kws.tool.service.UserVerifyService;
import com.kws.tool.verify.*;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.LinkedHashMap;

@Service
public class UserVerifyServiceImpl implements UserVerifyService {

    @Value("${verifyEqb.host}")
    private String host;
    @Value("${verifyEqb.appId}")
    private String appId;
    @Value("${verifyEqb.appKey}")
    private String appKey;


    /**
     * 实名校验-姓名-身份证
     *
     * @param userDto
     * @return
     */
    @Override
    public String aliVerify(UserDto userDto) {
        //获取用户的姓名和身份证号进行校验
        String userName = userDto.getUserName();
        String idCard = userDto.getIdCard();
        String result = null;
        try {
            result = AliIdCardReturnAddress.getResult(userName, idCard);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(result);
        return result;
    }

    @Override
    public ResultDto eVerify(UserDto userDto) {
        JSONObject str = testPost(appId, appKey, host, userDto);
        if (str==null){
            throw new RuntimeException("实名认证查询错误，请联系管理员！！");
        }
        ResultDto resultDto = JSONObject.parseObject(str.toJSONString(), ResultDto.class);
        return resultDto;
    }

    /**
     * e签宝-商家三要素认证-姓名-机构-机构号码
     * @param merchantDto
     * @return
     */
    @Override
    public ResultDto merchantVerify(MerchantDto merchantDto) {
        Factory.init(host,appId,appKey);//初始化，传入请求网关和应用id以及密钥,全局运行一次
        //{"code":0,"message":"成功","data":{"flowId":"3684353980878031027"}}
        //{"code":30504001,"message":"信息比对不通过,请检查信息的正确性","data":null}
        String name = merchantDto.getName();
        String legalRepName = merchantDto.getLegalRepName();
        String orgCode = merchantDto.getOrgCode();
        OrgThreeFactors orgThreeFactors = OrgIdentityVerify.orgThreeFactors(name, orgCode, legalRepName);
        OrgThreeFactorsResponse execute = null;
        try {
            execute = orgThreeFactors.execute();
        } catch (DefineException e) {
            e.printStackTrace();
        }
        ResultDto resultDto = JSONObject.parseObject(JSONObject.toJSONString(execute), ResultDto.class);
        return resultDto;
    }

    /**
     * e签宝-商家反向打款认证--flowId通过商家三要素认证得到
     * @param flowId
     * @return
     */
    @Override
    public ResultDto reverseRemit(String flowId) {
        Factory.init(host,appId,appKey);//初始化，传入请求网关和应用id以及密钥,全局运行一次
        ReversePayment reversePayment = OrgIdentityVerify.reversePayment(flowId);
        ReversePaymentResponse execute=null;
        try {
            execute = reversePayment.execute();
        } catch (DefineException e) {
            e.printStackTrace();
        }
        ResultDto resultDto = JSONObject.parseObject(JSONObject.toJSONString(execute), ResultDto.class);
        return resultDto;
    }

    public JSONObject testPost(String appId, String appKey, String host, UserDto userDto) {
        // 计算签名拼接的url
        String postUrl = "/v2/identity/verify/individual/base";
        // 完整的请求地址
        String postAllUrl = host + postUrl;


        try {
            // 构建请求Body体
            JSONObject reqBodyObj = new JSONObject();
//      reqBodyObj.put("contentMd5", "KMYh+0qU9/FDXf2TwCGbeg==");
//      reqBodyObj.put("contentType", "application/octet-stream");
//      reqBodyObj.put("convertToPDF", "true");
//      reqBodyObj.put("fileName", "销售合同.docx");
//      reqBodyObj.put("fileSize", "81825");
            //reqBodyObj.put("convertToHTML", "false");
            reqBodyObj.put("idNo", userDto.getIdCard());
            reqBodyObj.put("name", userDto.getUserName());
            // 请求Body体数据
            String reqBodyData = reqBodyObj.toString();
            // 对请求Body体内的数据计算ContentMD5
            String contentMD5 = doContentMD5(reqBodyData);
            System.out.println("请求body数据:" + reqBodyData);
            System.out.println("body的md5值：" + contentMD5);

            // 构建待签名字符串
            String method = "POST";
            String accept = "*/*";
            String contentType = "application/json";
            String url = postUrl;
            String date = "";
            String headers = "";

            StringBuffer sb = new StringBuffer();
            sb.append(method).append("\n").append(accept).append("\n").append(contentMD5).append("\n")
                    .append(contentType).append("\n").append(date).append("\n");
            if ("".equals(headers)) {
                sb.append(headers).append(url);
            } else {
                sb.append(headers).append("\n").append(url);
            }

            // 构建参与请求签名计算的明文
            String plaintext = sb.toString();
            // 计算请求签名值
            String reqSignature = doSignatureBase64(plaintext, appKey);
            System.out.println("计算请求签名值:" + reqSignature);

            // 获取时间戳(精确到毫秒)
            long timeStamp = timeStamp();

            // 构建请求头
            LinkedHashMap<String, String> header = new LinkedHashMap<String, String>();
            header.put("X-Tsign-Open-App-Id", appId);
            header.put("X-Tsign-Open-Auth-Mode", "Signature");
            header.put("X-Tsign-Open-Ca-Timestamp", String.valueOf(timeStamp));
            header.put("Accept", accept);
            header.put("Content-Type", contentType);
            header.put("X-Tsign-Open-Ca-Signature", reqSignature);
            header.put("Content-MD5", contentMD5);

            // 发送POST请求
            String result = HTTPHelper1.sendPOST(postAllUrl, reqBodyData, header, "UTF-8");
            JSONObject resultObj = JSONObject.parseObject(result);
            System.out.println("请求返回信息： " + resultObj.toString());
            return resultObj;
        } catch (Exception e) {
            e.printStackTrace();
            String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());
            System.out.println(msg);
        }
        return null;
    }
    /***
     * 获取时间戳(毫秒级)
     *
     * @return 毫秒级时间戳,如 1578446909000
     */
    public  long timeStamp() {
        long timeStamp = System.currentTimeMillis();
        return timeStamp;
    }
    /***
     *
     * @param str 待计算的消息
     * @return MD5计算后摘要值的Base64编码(ContentMD5)
     * @throws Exception 加密过程中的异常信息
     */
    public  String doContentMD5(String str) throws Exception {
        byte[] md5Bytes = null;
        MessageDigest md5 = null;
        String contentMD5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md5.update(str.getBytes("UTF-8"));
            // 获取文件MD5的二进制数组（128位）
            md5Bytes = md5.digest();
            // 把MD5摘要后的二进制数组md5Bytes使用Base64进行编码（而不是对32位的16进制字符串进行编码）
            contentMD5 = new String(Base64.encodeBase64(md5Bytes), "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            String msg = MessageFormat.format("不支持此算法: {0}", e.getMessage());
            Exception ex = new Exception(msg);
            ex.initCause(e);
            throw ex;
        } catch (UnsupportedEncodingException e) {
            String msg = MessageFormat.format("不支持的字符编码: {0}", e.getMessage());
            Exception ex = new Exception(msg);
            ex.initCause(e);
            throw ex;
        }
        return contentMD5;
    }

    /***
     * 计算请求签名值
     *
     * @param message 待计算的消息
     * @param secret 密钥
     * @return HmacSHA256计算后摘要值的Base64编码
     * @throws Exception 加密过程中的异常信息
     */
    public  String doSignatureBase64(String message, String secret) throws Exception {
        String algorithm = "HmacSHA256";
        Mac hmacSha256;
        String digestBase64 = null;
        try {
            hmacSha256 = Mac.getInstance(algorithm);
            byte[] keyBytes = secret.getBytes("UTF-8");
            byte[] messageBytes = message.getBytes("UTF-8");
            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm));
            // 使用HmacSHA256对二进制数据消息Bytes计算摘要
            byte[] digestBytes = hmacSha256.doFinal(messageBytes);
            // 把摘要后的结果digestBytes使用Base64进行编码
            digestBase64 = new String(Base64.encodeBase64(digestBytes), "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            String msg = MessageFormat.format("不支持此算法: {0}", e.getMessage());
            Exception ex = new Exception(msg);
            ex.initCause(e);
            throw ex;
        } catch (UnsupportedEncodingException e) {
            String msg = MessageFormat.format("不支持的字符编码: {0}", e.getMessage());
            Exception ex = new Exception(msg);
            ex.initCause(e);
            throw ex;
        } catch (InvalidKeyException e) {
            String msg = MessageFormat.format("无效的密钥规范: {0}", e.getMessage());
            Exception ex = new Exception(msg);
            ex.initCause(e);
            throw ex;
        }
        return digestBase64;
    }
}